﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfDrawCricle
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
            setUpEvent();
        }

        private void setUpEvent()
        {
            Button_Add.Click += new RoutedEventHandler(Button_Add_Click);
        }
        List<Ellipse> EllipsesSub = new List<Ellipse>();
        double changeBanKinh(double parentBK, double bankinh)
        {
            if(bankinh >= parentBK/2)
                return bankinh;
            var temp = parentBK / 2 - bankinh;
            return bankinh + Math.Sqrt(temp);
        }
        void Button_Add_Click(object sender, RoutedEventArgs e)
        {
            List<double> list = new List<double>() { 50, 25, 15, 7.5, 2.5 };
            var rate = bola.Width / 100.0;
            list = list.Select(c => c * rate).ToList(); ;
            BudgetChartHelper.CreateCircleChild(canvas, bola, list.ToArray());

            //double bankinh = bola3.Width / 2d;
            //bankinh = changeBanKinh(100, bankinh);
            //bola3.Width = bankinh * 2;
            //bola3.Height = bankinh * 2;
            //var pcenter =BudgetChartHelper.TimTamVongTronTXNvaOTrong(bola2, bola, bankinh);
            //var pLeftTop = BudgetChartHelper.TimLopLeftTuTamVaBanKinh(pcenter, bankinh);
            //bola3.SetValue(Canvas.LeftProperty, (double)pLeftTop.X); //set x
            //bola3.SetValue(Canvas.TopProperty, (double)pLeftTop.Y); //set y

            //EllipsesSub.Add(bola3);


            //Ellipse bola4 = new Ellipse();            
            //bola4.Fill = new SolidColorBrush(Colors.Azure);
            //canvas.Children.Add(bola4);
            //double bankinh4 = 40 / 2;
            //bankinh4 = changeBanKinh(100, bankinh4);
            //bola4.Width = bankinh4 * 2;
            //bola4.Height= bankinh4 * 2;
            //var pcenter4 = BudgetChartHelper.TimTamVongTronTXNvaOTrong(bola2, bola, bankinh4, EllipsesSub);//
            //var pLeftTop4 = BudgetChartHelper.TimLopLeftTuTamVaBanKinh(pcenter4, bankinh4);
            //bola4.SetValue(Canvas.LeftProperty, (double)pLeftTop4.X); //set x
            //bola4.SetValue(Canvas.TopProperty, (double)pLeftTop4.Y); //set y

        }

        private void canvas_MouseMove(object sender, MouseEventArgs e)
        {
            //Point punto = e.GetPosition(canvas);
            //int mouseX = (int)punto.X;
            //int mouseY = (int)punto.Y;
            //bola.SetValue(Canvas.LeftProperty, (double)mouseX); //set x
            //bola.SetValue(Canvas.LeftProperty, (double)mouseY); //set y
        }

       

    }
    public static class BudgetChartHelper
    {
        static double changeBanKinh(double parentBK, double bankinh)
        {
            if (bankinh >= parentBK / 2)
                return bankinh;
            var temp = parentBK / 2 - bankinh;
            return bankinh + Math.Sqrt(temp);
        }
        public static void CreateCircleChild(Canvas canvasCtrl,Ellipse parent, double[] childDKs)
        {
            childDKs = childDKs.OrderByDescending(c=> c).ToArray();
            Ellipse biggestBrother= null;
            if (childDKs.Length > 0)
            {
                var firstChild = childDKs[0];
                biggestBrother=CreateCircleChild(canvasCtrl, parent, firstChild);
            }
            //others
            var OthersChild = childDKs.Skip(1).ToArray();
            List<Ellipse> listOthers = new List<Ellipse>();
            for( int i =0;i<OthersChild.Length;i++)
            {
                var newEllipse = CreateCircleChild(canvasCtrl, parent, biggestBrother, listOthers, OthersChild[i]);
                listOthers.Add(newEllipse);
            }
        }
        public static Ellipse CreateCircle(double bankinh)
        {            
            var ellipse = new Ellipse();
            ellipse.Stroke = Brushes.Black;
            ellipse.StrokeThickness = 1;
            ellipse.Fill = new SolidColorBrush(Colors.Azure);
            ellipse.Width = bankinh * 2;
            ellipse.Height = bankinh * 2;
            ellipse.ToolTip = (bankinh * 2).ToString();
            return ellipse;
        }
        public static Ellipse CreateCircleChild(Canvas canvasCtrl, Ellipse parent, double firstChildDK)
        {
            double bankinh = firstChildDK / 2d;
            bankinh = changeBanKinh(100, bankinh);
            var ellipse = CreateCircle(bankinh);

            var pCenterParent =TimTamVongTron(parent);
            var pcenter = new Point();
            pcenter.Y = pCenterParent.Y;
            pcenter.X = pCenterParent.X - (parent.Width - firstChildDK)/2.0;

            var pLeftTop = BudgetChartHelper.TimLopLeftTuTamVaBanKinh(pcenter, bankinh);
            ellipse.SetValue(Canvas.LeftProperty, (double)pLeftTop.X); //set x
            ellipse.SetValue(Canvas.TopProperty, (double)pLeftTop.Y); //set y

            canvasCtrl.Children.Add(ellipse);
            return ellipse;
        }
        public static Ellipse CreateCircleChild(Canvas canvasCtrl, Ellipse parent, Ellipse biggestBrother, List<Ellipse> OtherBrothers, double childDK)
        {
            double bankinh = childDK / 2d;
            bankinh = changeBanKinh(100, bankinh);
            var ellipse = CreateCircle(bankinh);            
            canvasCtrl.Children.Add(ellipse);
            var pcenter4 = BudgetChartHelper.TimTamVongTronTXNvaOTrong(biggestBrother, parent, bankinh, OtherBrothers);//
            var pLeftTop4 = BudgetChartHelper.TimLopLeftTuTamVaBanKinh(pcenter4, bankinh);
            ellipse.SetValue(Canvas.LeftProperty, (double)pLeftTop4.X); //set x
            ellipse.SetValue(Canvas.TopProperty, (double)pLeftTop4.Y); //set y
            return ellipse;
        }

        #region Math
        public static bool IsChuaTrongHoacTiepXucTrong(Ellipse _ellipe1, Ellipse _ellipe2)
        {
            var pCenter1 = TimTamVongTron(_ellipe1);
            var pCenter2 = TimTamVongTron(_ellipe2);
            double chieuDai = GetDistanceBetweenPoints(pCenter1, pCenter2);
            double triTuyetDoiBanKinh = Math.Abs((_ellipe1.Width / 2d) - (_ellipe2.Width / 2d));
            if (chieuDai <= triTuyetDoiBanKinh)
                return true;
            return false;
        }
        public static bool IsChuaTrong(Ellipse _ellipe1, Ellipse _ellipe2)
        {
            var pCenter1 = TimTamVongTron(_ellipe1);
            var pCenter2 = TimTamVongTron(_ellipe2);
            double chieuDai = GetDistanceBetweenPoints(pCenter1, pCenter2);
            double triTuyetDoiBanKinh = Math.Abs((_ellipe1.Width / 2d) - (_ellipe2.Width / 2d));
            if (chieuDai < triTuyetDoiBanKinh)
                return true;
            return false;
        }
        public static bool IsChuaTrong(Ellipse _ellipe1, Point pCenter2, double bankinh2)
        {
            var pCenter1 = TimTamVongTron(_ellipe1);

            double chieuDai = GetDistanceBetweenPoints(pCenter1, pCenter2);
            double triTuyetDoiBanKinh = Math.Abs((_ellipe1.Width / 2d) - bankinh2);
            if (chieuDai < triTuyetDoiBanKinh)
                return true;
            return false;
        }
        public static bool IsLongNhau(Ellipse _ellipe1, Point pCenter2, double bankinh2)
        {
            var pCenter1 = TimTamVongTron(_ellipe1);

            double chieuDai = GetDistanceBetweenPoints(pCenter1, pCenter2);
            double triTuyetDoiBanKinh = Math.Abs((_ellipe1.Width / 2d) - bankinh2);
            double tong2BK = (_ellipe1.Width / 2d) + bankinh2;
            if (chieuDai > triTuyetDoiBanKinh
                && chieuDai < tong2BK)
                return true;
            return false;
        }
        public static bool IsNamTrongHoacTiepXucTrong(Point pCenter1, Point pCenter2, double bankinh1, double bankinh2)
        {

            double chieuDai = GetDistanceBetweenPoints(pCenter1, pCenter2);
            double triTuyetDoiBanKinh = Math.Abs(bankinh1 - bankinh2);
            if (chieuDai <= triTuyetDoiBanKinh)
                return true;
            return false;
        }
        public static bool IsTiepXucNgoai(Ellipse _ellipe1, Ellipse _ellipe2)
        {
            var pCenter1 = TimTamVongTron(_ellipe1);
            var pCenter2 = TimTamVongTron(_ellipe2);
            double chieuDai = GetDistanceBetweenPoints(pCenter1, pCenter2);
            double tongBanKinh = (_ellipe1.Width / 2d) + (_ellipe2.Width / 2d);
            if (chieuDai == tongBanKinh)
                return true;
            return false;
        }
        public static bool IsTiepXucNgoai(Point pCenter1, Point pCenter2, double bankinh1, double bankinh2)
        {

            double chieuDai = GetDistanceBetweenPoints(pCenter1, pCenter2);
            double tongBanKinh = bankinh2 + bankinh1;
            if (chieuDai == tongBanKinh)
                return true;
            return false;
        }
        public static double GetDistanceBetweenPoints(Point p, Point q)
        {
            double a = p.X - q.X;
            double b = p.Y - q.Y;
            double distance = Math.Sqrt(a * a + b * b);
            return distance;
        }
        static int radianStart = 90;
        public static Point TimTamVongTron(Ellipse _ellipe)
        {
            double _ellipe_top = Canvas.GetTop(_ellipe);
            double _ellipe_left = Canvas.GetLeft(_ellipe);
            double _ellipe_center_y = _ellipe_top + _ellipe.Height / 2;
            double _ellipe_center_x = _ellipe_left + _ellipe.Width / 2;
            return new Point(_ellipe_center_x, _ellipe_center_y);
        }
        /// <summary>
        /// Tim vong trong co ban kinh bang ban kinh cua _ellipe + bankinh
        /// tam : la tam cua _ellipe
        /// </summary>
        /// <param name="_ellipe"></param>
        /// <param name="bankinh"></param>
        /// <returns></returns>        
        public static Point[] TimCacDiemTrenVongTronLon(Ellipse _ellipe, double bankinh)
        {
            Point pCenter = TimTamVongTron(_ellipe);
            double bankinhLon = bankinh + _ellipe.Height / 2;
            List<Point> listPoints = new List<Point>();
            for (double anpha = 360; anpha > 0; anpha = anpha - 0.1)
            {
                var anphanSub = (anpha - 360 + radianStart) % 360;
                double x = pCenter.X + bankinhLon * (Math.Cos(anphanSub * Math.PI / 180d));
                double y = pCenter.Y + bankinhLon * (Math.Sin(anphanSub * Math.PI / 180d));
                listPoints.Add(new Point(x, y));
            }
            return listPoints.ToArray();
        }

        public static Point TimTamVongTronTXNvaOTrong(Ellipse _ellipseTXN, Ellipse _ellipseTXT, double bankinh)
        {
            double banKinhTXN = _ellipseTXN.Width / 2d;
            double banKinhTXT = _ellipseTXT.Width / 2d;
            Point pcenterTXN = TimTamVongTron(_ellipseTXN);
            Point pcenterTXT = TimTamVongTron(_ellipseTXT);
            Point pCenter = new Point();
            var listPoint = TimCacDiemTrenVongTronLon(_ellipseTXN, bankinh);
            foreach (var _point in listPoint)
            {

                bool isTiepXucNgoai = IsTiepXucNgoai(pcenterTXN, _point, banKinhTXN, bankinh);
                bool isTiepXucTrong = IsNamTrongHoacTiepXucTrong(pcenterTXT, _point, banKinhTXT, bankinh);
                if (isTiepXucNgoai && isTiepXucTrong)
                    return _point;
            }
            return pCenter;
        }

        public static bool IsCatCacEllipesKhac(List<Ellipse> _ellipsSub, Point point, double bankinh)
        {
            foreach (var ellip in _ellipsSub)
            {

                if (IsChuaTrong(ellip, point, bankinh)
                    ||
                    IsLongNhau(ellip, point, bankinh))
                    return true;
            }
            return false;
        }
        public static Point TimTamVongTronTXNvaOTrong(Ellipse _ellipseTXN, Ellipse _ellipseTXT, double bankinh, List<Ellipse> _ellipsSub)
        {
            double banKinhTXN = _ellipseTXN.Width / 2d;
            double banKinhTXT = _ellipseTXT.Width / 2d;
            Point pcenterTXN = TimTamVongTron(_ellipseTXN);
            Point pcenterTXT = TimTamVongTron(_ellipseTXT);
            Point pCenter = new Point();
            var listPoint = TimCacDiemTrenVongTronLon(_ellipseTXN, bankinh);
            foreach (var _point in listPoint)
            {

                bool isTiepXucNgoai = IsTiepXucNgoai(pcenterTXN, _point, banKinhTXN, bankinh);
                bool isTiepXucTrong = IsNamTrongHoacTiepXucTrong(pcenterTXT, _point, banKinhTXT, bankinh);
                bool isCatEllipKhac = IsCatCacEllipesKhac(_ellipsSub, _point, bankinh);
                if (isTiepXucNgoai && isTiepXucTrong && !isCatEllipKhac)
                    return _point;
            }
            return pCenter;
        }
        public static Point TimLopLeftTuTamVaBanKinh(Point pCenter, double bankinh)
        {
            double x = pCenter.X - bankinh;
            double y = pCenter.Y - bankinh;
            return new Point(x, y);
        }
        #endregion
    }
}
